home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume10 / ptoc / part12 < prev    next >
Encoding:
Text File  |  1987-07-28  |  62.1 KB  |  2,558 lines

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v10i076:  Pascal to C translator, Part12/12
  5. Message-ID: <729@uunet.UU.NET>
  6. Date: 30 Jul 87 00:31:10 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 2547
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: Per Bergsten <mcvax!enea!chalmers!holtec!perb>
  12. Posting-number: Volume 10, Issue 76
  13. Archive-name: ptoc/Part12
  14.  
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then unpack
  18. # it by saving it into a file and typing "sh file".  To overwrite existing
  19. # files, type "sh file -c".  You can also feed this as standard input via
  20. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  21. # will see the following message at the end:
  22. #        "End of archive 12 (of 12)."
  23. # Contents:  ptc.p.1
  24. if test -f 'ptc.p.1' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'ptc.p.1'\"
  26. else
  27. echo shar: Extracting \"'ptc.p.1'\" \(59347 characters\)
  28. sed "s/^X//" >'ptc.p.1' <<'END_OF_FILE'
  29. X(***************************************************************************)
  30. X(***************************************************************************)
  31. X(**                                      **)
  32. X(**    Copyright (C) 1987 by Per Bergsten, Gothenburg, Sweden          **)
  33. X(**                                      **)
  34. X(**    No part of this program, or parts derived from this program,      **)
  35. X(**    may be sold, hired or otherwise exploited without the author's      **)
  36. X(**    written consent.                          **)
  37. X(**                                      **)
  38. X(**    The program may be freely redistributed provided that:          **)
  39. X(**                                      **)
  40. X(**        1) the original program text, including this notice,      **)
  41. X(**           is reproduced unaltered,                  **)
  42. X(**        2) no charge (other than a nominal media cost) is      **)
  43. X(**           demanded for the copy.                  **)
  44. X(**                                      **)
  45. X(**    The program may be included in a package only on the condition      **)
  46. X(**    that the package as a whole is distributed at media cost.      **)
  47. X(**                                      **)
  48. X(***************************************************************************)
  49. X(***************************************************************************)
  50. X(**                                      **)
  51. X(**    The program ptc is a Pascal-to-C translator.              **)
  52. X(**    It accepts a correct Pascal program and creates a C program      **)
  53. X(**    with the same behaviour. It is not a complete compiler in the      **)
  54. X(**    sense that it does NOT do complete typechecking or error-      **)
  55. X(**    reporting. Only a minimal typecheck is done so that the meaning      **)
  56. X(**    of each construct can be determined. Therefore, an incorrect      **)
  57. X(**    Pascal program can easily cause the translator to malfunction.      **)
  58. X(**                                      **)
  59. X(***************************************************************************)
  60. X(***************************************************************************)
  61. X(**                                      **)
  62. X(**    Things which are known to be dependent on the underlying cha-      **)
  63. X(**    racterset are marked with a comment containing the word    CHAR.      **)
  64. X(**    Things that are known to be dependent on the host operating      **)
  65. X(**    system are marked with a comment containing the word OS.      **)
  66. X(**    Things known to be dependent on the cpu and/or the target C-      **)
  67. X(**    implementation are marked with the word CPU.              **)
  68. X(**    Things dependent on the target C-library are marked with LIB.      **)
  69. X(**                                      **)
  70. X(**    The code generated by the translator assumes that there    is a      **)
  71. X(**    C-implementation with at least a reasonable <stdio> library      **)
  72. X(**    since all input/output is implemented in terms of C functions      **)
  73. X(**    like fprintf(), getc(), fopen(), rewind() etc.              **)
  74. X(**    If the source-program uses Pascal functions like sin(), sqrt()      **)
  75. X(**    etc, there must also exist such functions in the C-library.      **)
  76. X(**                                      **)
  77. X(***************************************************************************)
  78. X(***************************************************************************)
  79. X
  80. Xprogram    ptc(input, output);
  81. X
  82. Xlabel    9999;                (* end of program        *)
  83. X
  84. Xconst    version        = '@(#)ptc.p    1.5  Date 87/05/01';
  85. X
  86. X    keytablen    = 38;        (* nr of keywords        *)
  87. X    keywordlen    = 10;        (* length of a keyword        *)
  88. X    othersym    = 'otherwise '; (* keyword for others        *)
  89. X    externsym    = 'external  '; (* keyword for external        *)
  90. X    dummysym    = '          '; (* dummy keyword        *)
  91. X
  92. X    (* a Pascal set is implemented as an array of "wordtype" where    *)
  93. X    (* each element contains bits numbered from 0 to "setbits"    *)
  94. X    wordtype    = 'unsigned short';    (* CPU *)
  95. X    setbits        = 15;            (* CPU *)
  96. X
  97. X    (* a Pascal file is implemented as a struct which (among other    *)
  98. X    (* things) contain a flag-field, currently 3 bits are used    *)
  99. X    filebits    = 'unsigned short';    (* flags for files    *)
  100. X    filefill    = 12;            (* 16 less used 3 bits    *)
  101. X
  102. X    maxsetrange    = 15;            (* nr of words in a set    *)
  103. X    scalbase    = 0;    (* ordinal value of first scalar member    *)
  104. X
  105. X    maxprio        = 7;
  106. X
  107. X    maxmachdefs    = 8;    (* max nr of machine integer types    *)
  108. X    machdeflen    = 16;    (* max length of machine int type name    *)
  109. X
  110. X    (* limit of identifier table, identifiers and strings are saved    *)
  111. X    (* in an array 0 .. maxblkcnt of ^ array 0 .. maxstrblk of char    *)
  112. X    maxstrblk    = 1023;
  113. X    maxblkcnt    = 63;
  114. X    maxstrstor    = 65535; (* maxstrstor should be ==
  115. X                    (maxblkcnt+1) * (maxstrblk+1) - 1 *)
  116. X
  117. X    maxtoknlen    = 127;    (* max size of token (i.e. identifier,
  118. X                   string or number); must be > keywordlen
  119. X                   and should be <= 256, see hashtokn()    *)
  120. X
  121. X    hashmax        = 64;    (* size of hashtable - 1        *)
  122. X
  123. X    null        = 0;    (* "impossible" character value, CHAR;
  124. X                   a char with this value is used as delimiter
  125. X                   of strings in "strstor" and in toknbuffers;
  126. X                   it is also used as end-of-input marker by
  127. X                   the input procedures in lexical analysis *)
  128. X
  129. X    minchar        = null;
  130. X    maxchar        = 127;    (* greatest possible character, CHAR; limits
  131. X                   the number of elements in type "char" *)
  132. X
  133. X    (* tmpfilename is used in the generated code to obtain names of
  134. X       temporary files for reset/rewrite, the last character is supplied
  135. X       by the reset/rewrite routine *)
  136. X    tmpfilename    = '"/tmp/ptc%d%c", getpid(), '; (* OS *)
  137. X
  138. X    (* some frequently used characters *)
  139. X    space        = ' ';
  140. X    tab1        = '    ';
  141. X    tab2        = '        ';
  142. X    tab3        = '            ';
  143. X    tab4        = '                ';
  144. X    bslash        = '\';
  145. X    nlchr        = '''\n''';
  146. X    ffchr        = '''\f''';
  147. X    nulchr        = '''\0''';
  148. X    spchr        = ''' ''';
  149. X    quote        = '''';
  150. X    cite        = '"';
  151. X    xpnent        = 'e';        (* exponent char in output. CPU    *)
  152. X    percent        = '%';
  153. X    uscore        = '_';
  154. X    badchr        = '?';        (* CHAR *)
  155. X    okchr        = quote;    (* CHAR *)
  156. X
  157. X    tabwidth    = 8;        (* width of a tab-stop. OS    *)
  158. X
  159. X    echo        = false;     (* echo input as read        *)
  160. X    diffcomm    = false;     (* comment delimiters different    *)
  161. X    lazyfor        = false;     (* compile for-stmts a la C    *)
  162. X    unionnew    = true;     (* malloc unions for variants    *)
  163. X
  164. X    inttyp        = 'int';    (* for predefined functions    *)
  165. X    chartyp        = 'char';
  166. X    setwtyp        = 'setword';
  167. X    setptyp        = 'setptr';
  168. X    floattyp    = 'float';
  169. X    doubletyp    = 'double';
  170. X    dblcast        = '(double)';    (* for predefined functions    *)
  171. X
  172. X    realtyp        = doubletyp;    (* user real-vars and functions    *)
  173. X
  174. X    voidtyp        = 'void';    (* for procedures         *)
  175. X    voidcast    = '(void)';
  176. X
  177. X    intlen        = 10;        (* length of written integer    *)
  178. X    fixlen        = 20;        (* length of written real    *)
  179. X
  180. Xtype
  181. X    hashtyp    = 0 .. hashmax;        (* index to hash-tables    *)
  182. X
  183. X    strindx    = 0 .. maxstrstor;    (* index to "strstor"        *)
  184. X
  185. X    (* string-table "strstor" is implemented as an array that is grown
  186. X       dynamically by adding blocks when needed *)
  187. X    strbidx    = 0 .. maxstrblk;
  188. X    strblk    = array [ strbidx ] of char;
  189. X    strptr    = ^ strblk;
  190. X    strbcnt    = 0 .. maxblkcnt;
  191. X
  192. X    (* table for stored identifiers *)
  193. X    (* an identifier in any scope is represented by an idnode which is
  194. X       hooked to a slot in "idtab" as determined by a hash-function.
  195. X       whenever the input procedures find an identifier its idnode is
  196. X       immediately located, or created, if none was found; the identifier
  197. X       is then always handled though a pointer to the idnode. the actual
  198. X       text of the identifier is stored in "strstor". *)
  199. X    idptr    = ^ idnode;
  200. X    idnode    = record
  201. X            inext    : idptr;    (* chain of idnode's    *)
  202. X            inref    : 0 .. 127;    (* # of refs to this id    *)
  203. X            ihash    : hashtyp;    (* its hash value    *)
  204. X            istr    : strindx;    (* index to "strstor"    *)
  205. X          end;
  206. X
  207. X    (* toknbuf is used to handle identifiers and strings in those situations
  208. X       where the actual text is of intrest *)
  209. X    toknidx    = 1 .. maxtoknlen;
  210. X    toknbuf    = array [ toknidx ] of char;
  211. X
  212. X    (* a type to hold Pascal keywords *)
  213. X    keyword    = packed array [ 1 .. keywordlen ] of char;
  214. X
  215. X    (* predefined identifier enumeration *)
  216. X    predefs = (
  217. X        dabs,        darctan,    dargc,        dargv,
  218. X        dboolean,    dchar,        dchr,        dclose,
  219. X        dcos,        ddispose,    deof,        deoln,
  220. X        dexit,        dexp,        dfalse,        dflush,
  221. X        dget,        dhalt,        dinput,        dinteger,
  222. X        dln,        dmaxint,    dmessage,    dnew,
  223. X        dodd,        dord,        doutput,    dpage,
  224. X        dpack,        dpred,        dput,        dread,
  225. X        dreadln,    dreal,        dreset,        drewrite,
  226. X        dround,        dsin,        dsqr,        dsqrt,
  227. X        dsucc,        dtext,        dtrue,        dtrunc,
  228. X        dtan,        dwrite,        dwriteln,    dunpack,
  229. X        dzinit,        dztring
  230. X    );
  231. X
  232. X    (* lexical symbol enumeration *)
  233. X    symtyp    = (
  234. X        (* keywords and eof are sorted alphabetically ...... *)
  235. X        sand,        sarray,        sbegin,        scase,
  236. X        sconst,        sdiv,        sdo,        sdownto,
  237. X        selse,        send,        sextern,    sfile,
  238. X        sfor,        sforward,    sfunc,        sgoto,
  239. X        sif,        sinn,        slabel,        smod,
  240. X        snil,        snot,        sof,        sor,
  241. X        sother,        spacked,    sproc,        spgm,
  242. X        srecord,    srepeat,    sset,        sthen,
  243. X        sto,        stype,        suntil,        svar,
  244. X        swhile,        swith,        seof,
  245. X        (* ...... sorted *)
  246. X                                sinteger,
  247. X        sreal,        sstring,    schar,        sid,
  248. X        splus,        sminus,        smul,        squot,
  249. X        sarrow,        slpar,        srpar,        slbrack,
  250. X        srbrack,    seq,        sne,        slt,
  251. X        sle,        sgt,        sge,        scomma,
  252. X        scolon,        ssemic,        sassign,    sdotdot,
  253. X        sdot
  254. X    );
  255. X    symset    = set of symtyp;
  256. X
  257. X    (* lexical symbol definition *)
  258. X    (* the lexical symbol holds a descriptor and the value of a symbol
  259. X       read by the input procedures; note that real values are represented
  260. X       as strings saved in "strstor" like ordinary strings to avoid using
  261. X       float-variables and float-arithmetic in the translator *)
  262. X    lexsym    =
  263. X        record
  264. X        case st : symtyp of
  265. X          sid:        (vid    : idptr);
  266. X          schar:    (vchr    : char);
  267. X          sinteger:    (vint    : integer);
  268. X          sreal:    (vflt    : strindx);
  269. X          sstring:    (vstr    : strindx);
  270. X        end;
  271. X
  272. X    (* enumeration of symnode variants *)
  273. X    ltypes = (
  274. X        lpredef,    lidentifier,    lfield,        lforward,
  275. X        lpointer,    lstring,    llabel,        lforwlab,
  276. X        linteger,    lreal,        lcharacter
  277. X    );
  278. X
  279. X    declptr    = ^ declnode;
  280. X    treeptr    = ^ treenode;
  281. X    symptr    = ^ symnode;
  282. X    (* identifier/literal symbol definition *)
  283. X    (* in a given scope an identifier or a label is uniquely represented
  284. X       by a "symnode"; in order to have a uniform treatment of all objects
  285. X       occurring in the same syntactical positions (and hence in the parse-
  286. X       tree) the literal constants are represented in a similar manner *)
  287. X    symnode    =
  288. X        record
  289. X        lsymdecl    : treeptr;    (* symbol decl. point    *)
  290. X        lnext        : symptr;    (* symtab chain pointer    *)
  291. X        ldecl        : declptr;    (* backptr to symtab    *)
  292. X        case lt : ltypes of
  293. X          lpredef,            (* a predefined id    *)
  294. X          lfield,            (* a record field    *)
  295. X          lpointer,            (* a pointer id        *)
  296. X          lidentifier,            (* an identifier    *)
  297. X          lforward:
  298. X            (
  299. X            lid    : idptr;    (* ptr to its idnode    *)
  300. X            lused    : boolean    (* true if symbol used    *)
  301. X            );
  302. X          lstring:            (* a string literal     *)
  303. X            (
  304. X            lstr    : strindx    (* index to "strstor"    *)
  305. X            );
  306. X          lreal:            (* a real literal    *)
  307. X            (
  308. X            lfloat    : strindx    (* index to "strstor"    *)
  309. X            );
  310. X          lforwlab,            (* a declared label    *)
  311. X          llabel:            (* label decl & defined    *)
  312. X            (
  313. X            lno    : integer;    (* label number        *)
  314. X            lgo    : boolean    (* non-local usage    *)
  315. X            );
  316. X          linteger:            (* an integer literal    *)
  317. X            (
  318. X            linum    : integer    (* its value        *)
  319. X            );
  320. X          lcharacter:            (* a character literal    *)
  321. X            (
  322. X            lchar    : char        (* its value        *)
  323. X            )
  324. X        end;
  325. X
  326. X    (* symbol table definition *)
  327. X    (* the symbol table consists of symnodes chained along the lnext
  328. X       field; the nodes are connected in reverse order of occurence (last
  329. X       declared, first in chain) in the slot in the declnode determined
  330. X       by the hashfunction; when a new scope is entered a new declnode is
  331. X       manufactured and the previous one is hooked to the dprev field, thus
  332. X       nested scopes are represented by a list of declnodes *)
  333. X    declnode = record
  334. X            dprev    : declptr;
  335. X            ddecl    : array [ hashtyp ] of symptr
  336. X           end;
  337. X
  338. X    (* enumeration of nodes in parse tree *)
  339. X    (* NOTE: the subrange [ assignment .. nil ]  have priorities *)
  340. X    treetyp    = (
  341. X        npredef,    npgm,        nfunc,        nproc,
  342. X        nlabel,        nconst,        ntype,        nvar,
  343. X        nvalpar,    nvarpar,    nparproc,    nparfunc,
  344. X        nsubrange,    nvariant,    nfield,        nrecord,
  345. X        narray,        nconfarr,    nfileof,    nsetof,
  346. X        nbegin,        nptr,        nscalar,    nif,
  347. X        nwhile,        nrepeat,    nfor,        ncase,
  348. X        nchoise,    ngoto,        nwith,        nwithvar,
  349. X        nempty,        nlabstmt,    nassign,    nformat,
  350. X        nin,        neq,        nne,        nlt,
  351. X        nle,        ngt,        nge,        nor,
  352. X        nplus,        nminus,        nand,        nmul,
  353. X        ndiv,        nmod,        nquot,        nnot,
  354. X        numinus,    nuplus,        nset,        nrange,
  355. X        nindex,        nselect,    nderef,        ncall,
  356. X        nid,        nchar,        ninteger,    nreal,
  357. X        nstring,    nnil,        npush,        npop,
  358. X        nbreak
  359. X    );
  360. X
  361. X    (* enumeration of predefined types *)
  362. X    pretyps = (
  363. X        tnone,        tboolean,    tchar,        tinteger,
  364. X        treal,        tstring,    tnil,        tset,
  365. X        ttext,        tpoly,        terror
  366. X    );
  367. X
  368. X    (* enumeration of some special attributes *)
  369. X    attributes = (
  370. X        anone, aregister, aextern, areference
  371. X    );
  372. X
  373. X    (* parse tree definition *)
  374. X    (* the sourceprogram is represented by a treestructure built from
  375. X       treenodes where each node corresponds to one syntactic form from
  376. X       the pascal program *)
  377. X    treenode =
  378. X        record
  379. X        tnext,            (* ptr to next node in a list    *)
  380. X        ttype,            (* pointer to nodes type    *)
  381. X        tup    : treeptr;    (* ptr to parent node        *) 
  382. X        case tt : treetyp of
  383. X          npredef:        (* predefined object decl    *)
  384. X            (
  385. X            tdef:        (* predefined object descr.    *)
  386. X                predefs;
  387. X            tobtyp:        (* object type            *)
  388. X                pretyps
  389. X            );
  390. X          npgm,            (* program declaration        *)
  391. X          nproc,        (* procedure declaration    *)
  392. X          nfunc:        (* function declaration        *)
  393. X            (
  394. X            tsubid,        (* subr. identifier (nid)    *)
  395. X            tsubpar,    (* parameter list        *)
  396. X            tfuntyp,    (* function type (nid)        *)
  397. X            tsublab,    (* label decl list (nlabel)    *)
  398. X            tsubconst,    (* const decl list (nconst)    *)
  399. X            tsubtype,    (* type decl list (ntype)    *)
  400. X            tsubvar,    (* var decl list (nvar)        *)
  401. X            tsubsub,    (* subr. decl (nproc/nfunc)    *)
  402. X            tsubstmt:    (* stmt. list (NOT nbegin)    *)
  403. X                treeptr;
  404. X            tstat:        (* static declaration level    *)
  405. X                integer;
  406. X            tscope:        (* symbol table for local id's    *)
  407. X                 declptr
  408. X            );
  409. X          nvalpar,        (* value parameter declaration    *)
  410. X          nvarpar,        (* var parameter declaration    *)
  411. X          nconst,        (* constant declaration        *)
  412. X          ntype,        (* type declaration        *)
  413. X          nfield,        (* record field declaration    *)
  414. X          nvar:            (* var declaration declaration    *)
  415. X            (
  416. X            tidl,        (* list of declared id's (nid)    *)
  417. X            tbind:        (* var/type-type, const-value    *)
  418. X                treeptr;
  419. X            tattr:        (* special attributes for vars    *)
  420. X                attributes
  421. X            );
  422. X          nparproc,        (* parameter procedure        *)
  423. X          nparfunc:        (* parameter function        *)
  424. X            (
  425. X            tparid,        (* parm proc/func id (nid)    *)
  426. X            tparparm,    (* parm proc/func parm decl    *)
  427. X            tpartyp:    (* parm func type (nid)        *)
  428. X                treeptr
  429. X            );
  430. X          nptr:            (* pointer constructor        *)
  431. X            (
  432. X            tptrid:        (* referenced type (nid)    *)
  433. X                treeptr;
  434. X            tptrflag:    (* have seen node before    *)
  435. X                boolean
  436. X            );
  437. X          nscalar:        (* scalar type constructor    *)
  438. X            (
  439. X            tscalid:    (* list of scalar ids (nid)    *)
  440. X                treeptr
  441. X            );
  442. X          nfileof,        (* file type constructor    *)
  443. X          nsetof:        (* set type constructor        *)
  444. X            (
  445. X            tof:        (* set/file component type    *)
  446. X                treeptr
  447. X            );
  448. X          nsubrange:        (* subrange type constructor    *)
  449. X            (
  450. X            tlo, thi:    (* subrange limits        *)
  451. X                treeptr
  452. X            );
  453. X          nvariant:        (* record variant constructor    *)
  454. X            (
  455. X            tselct,        (* selector list (constants)    *)
  456. X            tvrnt:        (* variant field decl (nrecord)    *)
  457. X                treeptr
  458. X            );
  459. X
  460. X        (* the tuid field is used to attach a name to variants since
  461. X           C requires all union members to have names *)
  462. X          nrecord:        (* record/variant constructor    *)
  463. X            (
  464. X            tflist,        (* fixed field list (nfield)    *)
  465. X            tvlist:        (* variant list (nvariant)    *)
  466. X                treeptr;
  467. X            tuid:        (* variant name            *)
  468. X                idptr;
  469. X            trscope:    (* symbol table for local id's    *)
  470. X                 declptr
  471. X            );
  472. X          nconfarr:        (* conformant array constructor    *)
  473. X            (
  474. X            tcindx,        (* index declaration        *)
  475. X            tindtyp,    (* conf. arr. index type (nid)    *)
  476. X            tcelem:        (* array element type decl    *)
  477. X                treeptr;
  478. X            tcuid:        (* variant name            *)
  479. X                idptr
  480. X            );
  481. X          narray:        (* array type constructor    *)
  482. X            (
  483. X            taindx,        (* index declaration        *)
  484. X            taelem:        (* array element type decl    *)
  485. X                treeptr
  486. X            );
  487. X          nbegin:        (* begin statement        *)
  488. X            (
  489. X            tbegin:        (* statement list        *)
  490. X                treeptr
  491. X            );
  492. X          nlabstmt:        (* labeled statement        *)
  493. X            (
  494. X            tlabno,        (* label number (nlabel)    *)
  495. X            tstmt:        (* statement            *)
  496. X                treeptr
  497. X            );
  498. X          ngoto:        (* goto statement        *)
  499. X            (
  500. X            tlabel:        (* label to go to (nlabel)    *)
  501. X                treeptr
  502. X            );
  503. X
  504. X          nassign:        (* assignment statement        *)
  505. X            (
  506. X            tlhs,        (* variable            *)
  507. X            trhs:        (* value            *)
  508. X                treeptr
  509. X            );
  510. X
  511. X        (* npush/npop is used in proc/func which have local variables
  512. X           used in local proc/funcs; those variables are converted to
  513. X           global ptrs initialized to reference the local variable *)
  514. X          npush,        (* init code for proc/func    *)
  515. X          npop:            (* exit code for proc/func    *)
  516. X            (
  517. X            tglob,        (* global identifier (nid)    *)
  518. X            tloc,        (* local identifier (nid)    *)
  519. X            ttmp:        (* temp store for global (nid)    *)
  520. X                treeptr
  521. X            );
  522. X
  523. X          nbreak:
  524. X            (
  525. X            tbrkid,        (* for-variable            *)
  526. X            tbrkxp:        (* value for break        *)
  527. X                treeptr
  528. X            );
  529. X
  530. X          ncall:        (* procedure/function call    *)
  531. X            (
  532. X            tcall,        (* called identifier        *)
  533. X            taparm:        (* actual paramters        *)
  534. X                treeptr
  535. X            );
  536. X          nif:            (* if statement            *)
  537. X            (
  538. X            tifxp,        (* conditional expression    *)
  539. X            tthen,        (* stmt execd if true condition    *)
  540. X            telse:        (* stmt execd if true condition    *)
  541. X                treeptr
  542. X            );
  543. X          nwhile:        (* while statemnet        *)
  544. X            (
  545. X            twhixp,        (* conditional expression    *)
  546. X            twhistmt:    (* stmt execd if true condition    *)
  547. X                treeptr
  548. X            );
  549. X          nrepeat:        (* repeat statement        *)
  550. X            (
  551. X            treptstmt,    (* statement list        *)
  552. X            treptxp:    (* conditional expression    *)
  553. X                treeptr
  554. X            );
  555. X          nfor:            (* for statement        *)
  556. X            (
  557. X            tforid,        (* loop control variable (nid)    *)
  558. X            tfrom,        (* initial value        *)
  559. X            tto,        (* final value            *)
  560. X            tforstmt:    (* stmt execd in loop        *)
  561. X                treeptr;
  562. X            tincr:        (* to/downto flag true <==> to    *)
  563. X                boolean
  564. X            );
  565. X          ncase:        (* case statement        *)
  566. X            (
  567. X            tcasxp,        (* selecting expression        *)
  568. X            tcaslst,    (* list of choises        *)
  569. X            tcasother:    (* default action        *)
  570. X                treeptr
  571. X            );
  572. X          nchoise:        (* a choise in a case-stmt    *)
  573. X            (
  574. X            tchocon,    (* list of constants        *)
  575. X            tchostmt:    (* execd statement        *)
  576. X                treeptr
  577. X            );
  578. X          nwith:        (* with statment        *)
  579. X            (
  580. X            twithvar,    (* list of variables (nwithvar)    *)
  581. X            twithstmt:    (* statement execd in new scope    *)
  582. X                treeptr
  583. X            );
  584. X
  585. X        (* the local symbol table holds identifiers, picked from
  586. X           the record fields, temporarily declared during parsing
  587. X           of remainder of with-statement; these identifiers are
  588. X           later converted into fields referenced through a ptr *)
  589. X          nwithvar:        (* variable in with statement    *)
  590. X            (
  591. X            texpw:        (* record variable        *)
  592. X                treeptr;
  593. X            tenv:        (* symbol table for local scope    *)
  594. X                declptr
  595. X            );
  596. X
  597. X          nindex:        (* array indexing expression    *)
  598. X            (
  599. X            tvariable,    (* indexed variable        *)
  600. X            toffset:    (* index expression        *)
  601. X                treeptr
  602. X            );
  603. X          nselect:        (* record field selection expr    *)
  604. X            (
  605. X            trecord,    (* record variable        *)
  606. X            tfield:        (* selected field (nid)        *)
  607. X                treeptr
  608. X            );
  609. X
  610. X        (* binary operators or constructors *)
  611. X          nrange,        (* .. (set range)    *)
  612. X          nformat,        (* :  (write format)    *)
  613. X          nin,            (* in            *)
  614. X          neq,            (* =            *)
  615. X          nne,            (* <>            *)
  616. X          nlt,            (* <            *)
  617. X          nle,            (* <=            *)
  618. X          ngt,            (* >            *)
  619. X          nge,            (* >=            *)
  620. X          nor,            (* or            *)
  621. X          nplus,        (* +            *)
  622. X          nminus,        (* -            *)
  623. X          nand,            (* and            *)
  624. X          nmul,            (* *            *)
  625. X          ndiv,            (* div            *)
  626. X          nmod,            (* mod            *)
  627. X          nquot:        (* /            *)
  628. X            (
  629. X            texpl,        (* left operand expr    *)
  630. X            texpr:        (* right operand expr    *)
  631. X                treeptr
  632. X            );
  633. X
  634. X        (* unary operators or constructors; note that uplus is
  635. X           used to represent any parenthesized expression *)
  636. X          nderef,        (* ^ (ptr dereference)    *)
  637. X          nnot,            (* not            *)
  638. X          nset,            (* [ ] (set constr)    *)
  639. X          nuplus,        (* +            *)
  640. X          numinus:        (* -            *)
  641. X            (
  642. X            texps:        (* operand expression    *)
  643. X                treeptr
  644. X            );
  645. X
  646. X          nid,            (* identifier in decl or stmt    *)
  647. X          nreal,        (* literal real (decl or stmt)    *)
  648. X          ninteger,        (* literal int ( - " - )    *)
  649. X          nchar,        (* literal char ( - " - )    *)
  650. X          nstring,        (* literal string ( - " - )    *)
  651. X          nlabel:        (* label (decl, defpt or use)    *)
  652. X            (
  653. X            tsym:
  654. X                symptr
  655. X            );
  656. X
  657. X          nnil,            (* nil (pointer constant)    *)
  658. X          nempty:        (* empty statement        *)
  659. X            ( );
  660. X        end;
  661. X
  662. X    (* "reserved" words and standard identifiers from C, C LIB and
  663. X        OS environment excluding those reserved in Pascal *)
  664. X    cnames = (
  665. X        cabort,        cbreak,        ccontinue,    cdefine,
  666. X        cdefault,    cdouble,    cedata,        cenum,
  667. X        cetext,        cextern,    cfgetc,        cfclose,
  668. X        cfflush,    cfloat,        cfloor,        cfprintf,
  669. X        cfputc,        cfread,        cfscanf,    cfwrite,
  670. X        cgetc,        cgetpid,    cint,        cinclude,
  671. X        clong,        clog,        cmain,        cmalloc,
  672. X        cprintf,    cpower,        cputc,        cread,
  673. X        creturn,    cregister,    crewind,    cscanf,
  674. X        csetbits,    csetword,    csetptr,    cshort,
  675. X        csigned,    csizeof,    csprintf,    cstdin,
  676. X        cstdout,    cstderr,    cstrncmp,    cstrncpy,
  677. X        cstruct,    cstatic,    cswitch,    ctypedef,
  678. X        cundef,        cungetc,    cunion,        cunlink,
  679. X        cunsigned,    cwrite
  680. X    );
  681. X
  682. X    (* these are the detected errors. some are user-errors,
  683. X       some are internal problems and some are host system errors *)
  684. X    errors    = (
  685. X        ebadsymbol,    elongstring,    elongtokn,    erange,
  686. X        emanytokn,    enotdeclid,    emultdeclid,    enotdecllab,
  687. X        emultdecllab,    emuldeflab,    ebadstring,    enulchr,
  688. X        ebadchar,    eeofcmnt,    eeofstr,    evarpar,
  689. X        enew,        esetbase,    esetsize,    eoverflow,
  690. X        etree,        etag,        euprconf,    easgnconf,
  691. X        ecmpconf,    econfconf,    evrntfile,    evarfile,
  692. X        emanymachs,    ebadmach
  693. X    );
  694. X
  695. X    machdefstr = packed array [ 1 .. machdeflen ] of char;
  696. X
  697. Xvar
  698. X    usemax,            (* program needs max-function        *)
  699. X    usejmps,        (* source program uses non-local gotos    *)
  700. X    usecase,        (* source program has case-statement    *)
  701. X    usesets,        (* source program uses set-operations    *)
  702. X    useunion,
  703. X    usediff,
  704. X    usemksub,
  705. X    useintr,
  706. X    usesge,
  707. X    usesle,
  708. X    useseq,
  709. X    usesne,
  710. X    usememb,
  711. X    useins,
  712. X    usescpy,
  713. X    usecomp,        (* source program uses string-compare    *)
  714. X    usefopn,        (* source program uses reset/rewrite    *)
  715. X    usescan,
  716. X    usegetl,
  717. X    usenilp,        (* source program uses nil-pointer     *)
  718. X    usebool    : boolean;    (* source program writes boolean-values    *)
  719. X
  720. X    top    : treeptr;    (* top of parsetree, result from parse    *)
  721. X
  722. X    setlst    : treeptr;    (* list of set-initializations        *)
  723. X    setcnt    : integer;    (* counter for setlst length        *)
  724. X
  725. X    currsym    : lexsym;    (* current lexical symbol        *)
  726. X
  727. X    keytab    : array [ 0 .. keytablen ] of    (* table of keywords    *)
  728. X            record
  729. X            wrd    : keyword;    (* keyword text        *)
  730. X            sym    : symtyp    (* corresponding symbol    *)
  731. X            end;
  732. X
  733. X    strstor    : array [ strbcnt ] of strptr;    (* store for strings    *)
  734. X    strfree    : strindx;            (* first free position    *)
  735. X    strleft    : strbidx;            (* room in last blk    *)
  736. X
  737. X    idtab    : array [ hashtyp ] of idptr;    (* hashed table of id's    *)
  738. X
  739. X    symtab    : declptr;            (* table of symbols    *)
  740. X
  741. X    statlvl,                (* static decl. level    *)
  742. X    maxlevel : integer;            (*  - " - maximum value    *) 
  743. X
  744. X    deftab    : array [ predefs ] of treeptr;    (* predefined idents.    *)
  745. X    defnams    : array [ predefs ] of symptr;    (*        - " -        *)
  746. X    typnods    : array [ pretyps ] of treeptr;    (* predef. types.    *)
  747. X
  748. X    pprio,
  749. X    cprio    : array [ nassign .. nnil ] of 0 .. maxprio;
  750. X
  751. X    ctable    : array [ cnames ] of idptr;    (* table of C-keywords    *)
  752. X
  753. X    nmachdefs : 0 .. maxmachdefs;
  754. X    machdefs : array [ 1 .. maxmachdefs ] of (* table of C-types    *)
  755. X            record
  756. X                lolim, hilim    : integer;
  757. X                typstr        : strindx
  758. X            end;
  759. X
  760. X    lineno,                    (* input line number    *)
  761. X    colno,                    (* input column number    *)
  762. X    lastcol,                (* last OK input column    *)
  763. X    lastline : integer;            (* last OK input line    *)
  764. X
  765. X    lasttok    : toknbuf;            (* last input token    *)
  766. X
  767. X    varno    : integer;        (* counter for unique id's    *)
  768. X
  769. X    hexdig    : packed array [ 0 .. 15 ] of char;
  770. X
  771. X(*    Prtmsg produces an error message. It asssumes that procedure    *)
  772. X(*    "message" (predefined) will "writeln" to user tty. OS        *)
  773. Xprocedure prtmsg(m : errors);
  774. X
  775. Xconst    user    = 'Error: ';
  776. X    restr    = 'Implementation restriction: ';
  777. X    inter    = '* Internal error * ';
  778. X    xtoklen    = 64;                (* should be <= maxtoklen *)
  779. X
  780. Xvar    i    : toknidx;
  781. X    xtok    : packed array [ 1 .. xtoklen ] of char;
  782. X
  783. Xbegin
  784. X    case m of
  785. X      ebadsymbol:
  786. X        message(user, 'Unexpected symbol');
  787. X      ebadchar:
  788. X        message(user, 'Bad character');
  789. X      elongstring:
  790. X        message(restr, 'Too long string');
  791. X      ebadstring:
  792. X        message(user, 'Newline in string or character');
  793. X      eeofstr:
  794. X        message(user, 'End of file in string or character');
  795. X      eeofcmnt:
  796. X        message(user, 'End of file in comment');
  797. X      elongtokn:
  798. X        message(restr, 'Too long identfier');
  799. X      emanytokn:
  800. X        message(restr, 'Too many strings, identifiers or real numbers');
  801. X      enotdeclid:
  802. X        message(user, 'Identifier not declared');
  803. X      emultdeclid:
  804. X        message(user, 'Identifier declared twice');
  805. X      enotdecllab:
  806. X        message(user, 'Label not declared');
  807. X      emultdecllab:
  808. X        message(user, 'Label declared twice');
  809. X      emuldeflab:
  810. X        message(user, 'Label defined twice');
  811. X      evarpar:
  812. X        message(user, 'Actual parameter not a variable');
  813. X      enulchr:
  814. X        message(restr, 'Cannot handle nul-character in strings');
  815. X      enew:
  816. X        message(restr, 'New returned a nil-pointer');
  817. X      eoverflow:
  818. X        message(restr, 'Token buffer overflowed');
  819. X      esetbase:
  820. X        message(restr, 'Cannot handle sets with base >> 0');
  821. X      esetsize:
  822. X        message(restr, 'Cannot handle sets with very large range');
  823. X      etree:
  824. X        message(inter, 'Bad tree structure');
  825. X      etag:
  826. X        message(inter, 'Cannot find tag');
  827. X      evrntfile:
  828. X        message(restr, 'Cannot initialize files in record variants');
  829. X      evarfile:
  830. X        message(restr, 'Cannot handle files in structured variables');
  831. X      euprconf:
  832. X        message(inter, 'No upper bound on conformant arrays');
  833. X      easgnconf:
  834. X        message(inter, 'Cannot assign conformant arrays');
  835. X      ecmpconf:
  836. X        message(inter, 'Cannot compare conformant arrays');
  837. X      econfconf:
  838. X        message(restr, 'Cannot handle nested conformat arrays');
  839. X      erange:
  840. X        message(inter, 'Cannot find C-type for integer-subrange');
  841. X      emanymachs:
  842. X        message(restr, 'Too many machine integer types');
  843. X      ebadmach:
  844. X        message(inter, 'Bad name for machine integer type');
  845. X    end;(* case *)
  846. X    if lastline <> 0 then
  847. X        begin
  848. X        (* error detected during parsing,
  849. X            report line/column and print the offending symbol *)
  850. X        message('Line ', lastline:1, ', col ', lastcol:1, ':');
  851. X        if m in [enulchr, ebadchar, ebadstring, ebadsymbol,
  852. X            emuldeflab, emultdecllab, enotdecllab, emultdeclid,
  853. X            enotdeclid, elongtokn, elongstring] then
  854. X            begin
  855. X            i := 1;
  856. X            while (i < xtoklen) and (lasttok[i] <> chr(null)) do
  857. X                begin
  858. X                xtok[i] := lasttok[i];
  859. X                i := i + 1
  860. X                end;
  861. X            while i < xtoklen do
  862. X                begin
  863. X                xtok[i] := ' ';
  864. X                i := i + 1
  865. X                end;
  866. X            xtok[xtoklen] := ' ';
  867. X            message('Current symbol: ', xtok)
  868. X            end
  869. X        end
  870. Xend;
  871. X
  872. Xprocedure fatal(m : errors);    forward;
  873. Xprocedure error(m : errors);    forward;
  874. X
  875. X(*    Map letters to upper-case.                    *)
  876. X(*    This function assumes a machine collating sequence where the    *)
  877. X(*    letters of either case form a contigous sequence, CHAR.    *)
  878. Xfunction uppercase(c : char) : char;
  879. X
  880. Xbegin
  881. X    if (c >= 'a') and (c <= 'z') then
  882. X        uppercase := chr(ord(c) + ord('A') - ord('a'))
  883. X    else
  884. X        uppercase := c
  885. Xend;
  886. X
  887. X
  888. X(*    Map letters to lower-case.                    *)
  889. X(*    This function assumes a machine collating sequence where the    *)
  890. X(*    letters of either case form a contigous sequence, CHAR.    *)
  891. Xfunction lowercase(c : char) : char;
  892. X
  893. Xbegin
  894. X    if (c >= 'A') and (c <= 'Z') then
  895. X        lowercase := chr(ord(c) - ord('A') + ord('a'))
  896. X    else
  897. X        lowercase := c
  898. Xend;
  899. X
  900. X(*    Retrieve a string from strstor.                *)
  901. Xprocedure gettokn(i : strindx; var t : toknbuf);
  902. X
  903. Xvar    c    : char;
  904. X    k    : toknidx;
  905. X    j    : strbidx;
  906. X    p    : strptr;
  907. X
  908. Xbegin
  909. X    k := 1;
  910. X    (* compute block and offset in block *)
  911. X    p := strstor[i div (maxstrblk + 1)];
  912. X    j := i mod (maxstrblk + 1);
  913. X    (* retrieve text up to null *)
  914. X    repeat
  915. X        c := p^[j];
  916. X        t[k] := c;
  917. X        j := j + 1;
  918. X        k := k + 1;
  919. X        if k = maxtoknlen then
  920. X            begin
  921. X            c := chr(null);
  922. X            t[maxtoknlen] := chr(null);
  923. X            prtmsg(eoverflow)
  924. X            end
  925. X    until    c = chr(null)
  926. Xend;
  927. X
  928. X(*    Deposit a string into strstor at a given start-position.    *)
  929. Xprocedure puttokn(i : strindx; var t : toknbuf);
  930. X
  931. Xvar    c    : char;
  932. X    k    : toknidx;
  933. X    j    : strbidx;
  934. X    p    : strptr;
  935. X
  936. Xbegin
  937. X    k := 1;
  938. X    p := strstor[i div (maxstrblk + 1)];
  939. X    j := i mod (maxstrblk + 1);
  940. X    repeat
  941. X        c := t[k];
  942. X        p^[j] := c;
  943. X        k := k + 1;
  944. X        j := j + 1
  945. X    until    c = chr(null)
  946. Xend;
  947. X
  948. X(*    Write a token on standard output.                *)
  949. Xprocedure writetok(var w : toknbuf);
  950. X
  951. Xvar    j    : toknidx;
  952. X
  953. Xbegin
  954. X    j := 1;
  955. X    while w[j] <> chr(null) do
  956. X        begin
  957. X        write(w[j]);
  958. X        j := j + 1
  959. X        end
  960. Xend;
  961. X
  962. X(*    Print a float number on standard output.            *)
  963. Xprocedure printtok(i : strindx);
  964. X
  965. Xvar    w    : toknbuf;
  966. X
  967. Xbegin
  968. X    gettokn(i, w);
  969. X    writetok(w)
  970. Xend;
  971. X
  972. X(*    Print an identifier on standard output.                *)
  973. Xprocedure printid(ip : idptr);
  974. X
  975. Xbegin
  976. X    printtok(ip^.istr)
  977. Xend;
  978. X
  979. X(*    Print a character on standard output with proper C-quoting.    *)
  980. Xprocedure printchr(c : char);
  981. X
  982. Xbegin
  983. X    if (c = quote) or (c = bslash) then
  984. X        write(quote, bslash, c, quote)
  985. X    else
  986. X        write(quote, c, quote)
  987. Xend;
  988. X
  989. X(*    Print a string on standard output with proper C-quoting.    *)
  990. Xprocedure printstr(i : strindx);
  991. X
  992. Xvar    k    : toknidx;
  993. X    c    : char;
  994. X    w    : toknbuf;
  995. X
  996. Xbegin
  997. X    gettokn(i, w);
  998. X    write(cite);
  999. X    k := 1;
  1000. X    while w[k] <> chr(null) do
  1001. X        begin
  1002. X        c := w[k];
  1003. X        k := k + 1;
  1004. X        if (c = cite) or (c = bslash) then
  1005. X            write(bslash);
  1006. X        write(c)
  1007. X        end;
  1008. X    write(cite)
  1009. Xend;
  1010. X
  1011. X(*    Return a pointer to the declarationpoint of an identifier.    *)
  1012. Xfunction idup(ip : treeptr) : treeptr;
  1013. X
  1014. Xbegin
  1015. X    idup := ip^.tsym^.lsymdecl^.tup
  1016. Xend;
  1017. X
  1018. X(*    Compute a hashvalue for an identifier or a string.        *)
  1019. Xfunction hashtokn(var id : toknbuf) : hashtyp;
  1020. X
  1021. Xvar    h    : integer;
  1022. X    i    : toknidx;
  1023. X
  1024. Xbegin
  1025. X    i := 1;
  1026. X    h := 0;
  1027. X    while id[i] <> chr(null) do
  1028. X        begin
  1029. X        (* if ord() of a character ranges from 0 to 127 then we can loop
  1030. X           256 times without causing h to exceed 32767, this is safe as
  1031. X           both strings and identifiers are limited in length *)
  1032. X        h := h + ord(id[i]);    (* CHAR, CPU *)
  1033. X        i := i + 1
  1034. X        end;
  1035. X    hashtokn := h mod hashmax
  1036. Xend;
  1037. X
  1038. X(*    Global string table update.                    *)
  1039. X(*    This function accepts a string and stores it in strstor.    *)
  1040. X(*    It returns the id-number for the new string.            *)
  1041. Xfunction savestr(var t : toknbuf) : strindx;
  1042. X
  1043. Xvar    k    : toknidx;
  1044. X    i    : strindx;
  1045. X    j    : strbcnt;
  1046. X
  1047. Xbegin
  1048. X    (* find length of new string including null-char *)
  1049. X    k := 1;
  1050. X    while t[k] <> chr(null) do
  1051. X        k := k + 1;
  1052. X    if k > strleft then
  1053. X        begin
  1054. X        (* out of space in strstore *)
  1055. X        if strstor[maxblkcnt] <> nil then    (* last slot used *)
  1056. X            error(emanytokn);
  1057. X        (* allocate a new block *)
  1058. X        j := (strfree + maxstrblk) div (maxstrblk + 1);
  1059. X        new(strstor[j]);
  1060. X        if strstor[j] = nil then
  1061. X            error(enew);
  1062. X        strfree := j * (maxstrblk + 1);
  1063. X        strleft := maxstrblk
  1064. X        end;
  1065. X    (* copy new str, update location of last used cell,
  1066. X       return starting location for new str *)
  1067. X    i := strfree;
  1068. X    strfree := strfree + k;
  1069. X    strleft := strleft - k;
  1070. X    puttokn(i, t);
  1071. X    savestr := i
  1072. Xend;
  1073. X
  1074. X(*    Global id table lookup.                        *)
  1075. X(*    This procedure accepts an identifier and determines if it has    *)
  1076. X(*    been seen before. If that is the case a pointer to its idnode    *)
  1077. X(*    is returned, otherwise the identifier is saved and a pointer to    *)
  1078. X(*    a new node is returned.                        *)
  1079. Xfunction saveid(var id : toknbuf) : idptr;
  1080. X
  1081. Xlabel    999;
  1082. X
  1083. Xvar    k    : toknidx;
  1084. X    ip    : idptr;
  1085. X    h    : hashtyp;
  1086. X    t    : toknbuf;
  1087. X
  1088. Xbegin
  1089. X    h := hashtokn(id);
  1090. X    ip := idtab[h];                (* scan hashlist for id    *)
  1091. X    while ip <> nil do
  1092. X        begin
  1093. X        gettokn(ip^.istr, t);        (* look at saved token    *)
  1094. X        k := 1;
  1095. X        while id[k] = t[k] do
  1096. X            if id[k] = chr(null) then
  1097. X                goto 999    (* found it!        *)
  1098. X            else
  1099. X                k := k + 1;    (* look at next char    *)
  1100. X        ip := ip^.inext
  1101. X        end;
  1102. X
  1103. X    (* identifier wasn't previously seen, manufacture a new idnode,
  1104. X       save index to strstor and hashvalue, insert idnode in idtab *)
  1105. X    new(ip);
  1106. X    if ip = nil then
  1107. X        error(enew);
  1108. X    ip^.inref := 0;
  1109. X    ip^.istr := savestr(id);
  1110. X    ip^.ihash := h;
  1111. X    ip^.inext := idtab[h];
  1112. X    idtab[h] := ip;
  1113. X
  1114. X999:
  1115. X    (* return the idnode *)
  1116. X    saveid := ip
  1117. Xend;
  1118. X
  1119. X(*    This function creates a new variable by concatenating one name    *)
  1120. X(*    with another injecting a given separator.            *)
  1121. Xfunction mkconc(sep : char; p, q : idptr) : idptr;
  1122. X
  1123. Xvar    w, x    : toknbuf;
  1124. X    i, j    : toknidx;
  1125. X
  1126. Xbegin
  1127. X    (* fetch second part and determine its length *)
  1128. X    gettokn(q^.istr, x);
  1129. X    j := 1;
  1130. X    while x[j] <> chr(null) do
  1131. X        j := j + 1;
  1132. X    (* fetch first part and locate its end *)
  1133. X    w[1] := chr(null);
  1134. X    if p <> nil then
  1135. X        gettokn(p^.istr, w);
  1136. X    i := 1;
  1137. X    while w[i] <> chr(null) do
  1138. X        i := i + 1;
  1139. X    (* check total length *)
  1140. X    if i + j + 2 >= maxtoknlen then
  1141. X        error(eoverflow);
  1142. X
  1143. X    (* add separators *)
  1144. X    if sep = '>' then
  1145. X        begin
  1146. X        (* special case 1: > gives arrow: a->b *)
  1147. X        w[i] := '-';
  1148. X        i := i + 1
  1149. X        end;
  1150. X    if sep <> space then
  1151. X        begin
  1152. X        (* special case 2: space gives nothing: ab *)
  1153. X        w[i] := sep;
  1154. X        i := i + 1
  1155. X        end;
  1156. X    (* add second part *)
  1157. X    j := 1;
  1158. X    repeat
  1159. X        w[i] := x[j];
  1160. X        i := i + 1;
  1161. X        j := j + 1
  1162. X    until w[i-1] = chr(null);
  1163. X    (* save new identifier *)
  1164. X    mkconc := saveid(w)
  1165. Xend;
  1166. X
  1167. X(*    Create a new id with name-prefix from w.            *)
  1168. Xfunction mkuniqname(var t : toknbuf) : idptr;
  1169. X
  1170. Xvar    i    : toknidx;
  1171. X
  1172. X    procedure dig(n : integer);
  1173. X    begin
  1174. X        if n > 0 then
  1175. X            begin
  1176. X            dig(n div 10);
  1177. X            if i = maxtoknlen then
  1178. X                error(eoverflow);
  1179. X            t[i] := chr(n mod 10 + ord('0'));    (* CHAR *)
  1180. X            i := i + 1
  1181. X            end
  1182. X    end;
  1183. X
  1184. Xbegin
  1185. X    i := 1;
  1186. X    while t[i] <> chr(null) do
  1187. X        i := i + 1;
  1188. X    varno := varno + 1;
  1189. X    dig(varno);
  1190. X    t[i] := chr(null);
  1191. X    mkuniqname := saveid(t)
  1192. Xend;
  1193. X
  1194. X(*    Make a new unique variable with given char as prefix.        *)
  1195. Xfunction mkvariable(c : char) : idptr;
  1196. X
  1197. Xvar    t    : toknbuf;
  1198. X
  1199. Xbegin
  1200. X    t[1] := c;
  1201. X    t[2] := chr(null);
  1202. X    mkvariable := mkuniqname(t)
  1203. Xend;
  1204. X
  1205. X(*    Make a new unique variable with given char as prefix and    *)
  1206. X(*    with a given id as tail. Commonly used for renaming id's.    *)
  1207. Xfunction mkrename(c : char; ip : idptr) : idptr;
  1208. X
  1209. Xbegin
  1210. X    mkrename := mkconc(uscore, mkvariable(c), ip)
  1211. Xend;
  1212. X
  1213. X(*    Make a name for a variant. Variants are mapped onto C unions,    *)
  1214. X(*    which we always give the name "U", thus the name of the variant    *)
  1215. X(*    becomes "U.Vnnn" where "nnn" is a unique number.        *)
  1216. Xfunction mkvrnt : idptr;
  1217. X
  1218. Xvar    t    : toknbuf;
  1219. X
  1220. Xbegin
  1221. X    t[1] := 'U';
  1222. X    t[2] := '.';
  1223. X    t[3] := 'V';
  1224. X    t[4] := chr(null);
  1225. X    mkvrnt := mkuniqname(t)
  1226. Xend;
  1227. X
  1228. Xprocedure checksymbol(ss : symset);
  1229. Xbegin
  1230. X    if not (currsym.st in ss) then
  1231. X        error(ebadsymbol);
  1232. Xend;
  1233. X
  1234. X(*    Lexical analysis routine.                    *)
  1235. X(*    This procedure reads and classifies the next lexical token in    *)
  1236. X(*    the input stream. The token is saved in the global variable    *)
  1237. X(*    "currsym". The found symbol should be one of the symbols given    *)
  1238. X(*    in the parameter "ss" otherwise the error routine is called.    *)
  1239. Xprocedure nextsymbol(ss : symset);
  1240. X
  1241. Xvar    lastchr    : 0 .. maxtoknlen;
  1242. X
  1243. X    (*    This function reads the next character from the input    *)
  1244. X    (*    and updates "lineno" and "colno" accordingly.        *)
  1245. X    function nextchar : char;
  1246. X
  1247. X    var    c    : char;
  1248. X
  1249. X    begin
  1250. X        if eof then
  1251. X            c := chr(null)
  1252. X        else begin
  1253. X            colno := colno + 1;
  1254. X            if eoln then
  1255. X                begin
  1256. X                lineno := lineno + 1;
  1257. X                colno := 0
  1258. X                end;
  1259. X            read(c);
  1260. X            if echo then
  1261. X                if colno = 0 then
  1262. X                    writeln
  1263. X                else
  1264. X                    write(c);
  1265. X            if c = tab1 then
  1266. X                colno := ((colno div tabwidth) + 1) * tabwidth
  1267. X             end;
  1268. X        if lastchr > 0 then
  1269. X            begin
  1270. X            lasttok[lastchr] := c;
  1271. X            lastchr := lastchr + 1
  1272. X            end;
  1273. X        nextchar := c
  1274. X    end;
  1275. X
  1276. X    (*    This function looks at the next input character.    *)
  1277. X    function peekchar : char;
  1278. X
  1279. X    begin
  1280. X        if eof then
  1281. X            peekchar := chr(null)
  1282. X        else
  1283. X            peekchar := input^
  1284. X    end;
  1285. X
  1286. X    (*    Read and classify the next token.            *)
  1287. X    procedure nexttoken(realok : boolean);
  1288. X
  1289. X    var    c    : char;
  1290. X        n    : integer;
  1291. X
  1292. X        ready    : boolean;
  1293. X
  1294. X        wl    : toknidx;
  1295. X        wb    : toknbuf;
  1296. X
  1297. X        (*    Determine if c is valid in an identifier.    *)
  1298. X        (*    This function assumes a machine collating    *)
  1299. X        (*    sequence where letters and digits form conti-    *)
  1300. X        (*    gous sequences, CHAR.                *)
  1301. X        function idchar(c : char) : boolean;
  1302. X
  1303. X        begin
  1304. X            idchar := 
  1305. X                (c >= 'a') and (c <= 'z') or
  1306. X                    (c >= '0') and (c <= '9') or
  1307. X                    (c >= 'A') and (c <= 'Z') or
  1308. X                        (c = uscore)
  1309. X        end;
  1310. X
  1311. X        (*    Determine if c is valid in a number. CHAR.    *)
  1312. X        function numchar(c : char) : boolean;
  1313. X
  1314. X        begin
  1315. X            numchar := (c >= '0') and (c <= '9')
  1316. X        end;
  1317. X
  1318. X        (*    Convert a digit to its numeric value. CHAR    *)
  1319. X        function numval(c : char) : integer;
  1320. X
  1321. X        begin
  1322. X            numval := ord(c) - ord('0')
  1323. X        end;
  1324. X
  1325. X        (*    Determine if the current token is a keyword.    *)
  1326. X        function keywordcheck(var w : toknbuf; l : toknidx) : symtyp;
  1327. X
  1328. X        var    n    : 1 .. keywordlen;
  1329. X            i, j, k    : 0 .. keytablen;
  1330. X            wrd    : keyword;
  1331. X            kwc    : symtyp;
  1332. X
  1333. X        begin
  1334. X            (* quick check on token length,
  1335. X               pascal keywords range from 2 to 9 chars in length *)
  1336. X            if (l > 1) and (l < keywordlen) then
  1337. X                begin
  1338. X                (* could be a keyword, initialize wrd *)
  1339. X                wrd := keytab[keytablen].wrd;
  1340. X                (* copy w to wrd *)
  1341. X                for n := 1 to l do
  1342. X                    wrd[n] := w[n];
  1343. X
  1344. X                (* binary search for tokn,
  1345. X                   relies on symtyp being sorted *)
  1346. X                i := 0;
  1347. X                j := keytablen;
  1348. X                while j > i do
  1349. X                    begin
  1350. X                    k := (i + j) div 2;
  1351. X                    if keytab[k].wrd >= wrd then
  1352. X                        j := k
  1353. X                    else
  1354. X                        i := k + 1
  1355. X                    end;
  1356. X                if keytab[j].wrd = wrd then
  1357. X                    kwc := keytab[j].sym
  1358. X                else
  1359. X                    kwc := sid
  1360. X                end
  1361. X            else
  1362. X                kwc := sid;
  1363. X            keywordcheck := kwc
  1364. X        end;
  1365. X
  1366. X    begin    (* nexttoken *)
  1367. X        (* don't save blanks/comments *)
  1368. X        lastchr := 0;
  1369. X        (* read non-blank character *)
  1370. X        repeat
  1371. X            c := nextchar;
  1372. X            (* skip comments, the two comment delimiters of pascal
  1373. X               are treated as different if "diffcomm" is true *)
  1374. X            if c = '{' then
  1375. X                begin
  1376. X                repeat
  1377. X                    c := nextchar;
  1378. X                    if diffcomm then
  1379. X                        ready := c = '}'
  1380. X                    else
  1381. X                        ready := ((c = '*') and
  1382. X                                (peekchar = ')'))
  1383. X                            or (c = '}')
  1384. X                until ready or eof;
  1385. X                if eof and not ready then
  1386. X                    error(eeofcmnt);
  1387. X                if (c = '*') and not eof then
  1388. X                    c := nextchar;
  1389. X                c := space
  1390. X                end
  1391. X            else if (c = '(') and (peekchar = '*')  then
  1392. X                begin
  1393. X                c := nextchar;
  1394. X                repeat
  1395. X                    c := nextchar;
  1396. X                    if diffcomm then
  1397. X                        ready := (c = '*') and
  1398. X                            (peekchar = ')')
  1399. X                    else
  1400. X                        ready := ((c = '*') and
  1401. X                                (peekchar = ')'))
  1402. X                            or (c = '}')
  1403. X                until ready or eof;
  1404. X                if eof and not ready then
  1405. X                    error(eeofcmnt);
  1406. X                if (c = '*') and not eof then
  1407. X                    c := nextchar;
  1408. X                c := space
  1409. X                end
  1410. X        until    (c <> space) and (c <> tab1);
  1411. X
  1412. X        (* save characters from this token and save line- and column-
  1413. X           numbers for errormessages *)
  1414. X        lasttok[1] := c;
  1415. X        lastchr := 2;
  1416. X        lastcol := colno;
  1417. X        lastline := lineno;
  1418. X
  1419. X        (* map all CHAR control characters onto "badchr" *)
  1420. X        if c < okchr then
  1421. X            c := badchr;
  1422. X
  1423. X        (* decode symbol *)
  1424. X        with currsym do
  1425. X            if eof then
  1426. X            begin
  1427. X                lasttok[1] := '*';
  1428. X                lasttok[2] := 'E';
  1429. X                lasttok[3] := 'O';
  1430. X                lasttok[4] := 'F';
  1431. X                lasttok[5] := '*';
  1432. X                lastchr := 6;
  1433. X                st := seof
  1434. X            end
  1435. X            else
  1436. X            case c of
  1437. X
  1438. X
  1439. X            (* CHAR, chars not in Pascal *)
  1440. X              '|', '`', '~', '}',
  1441. X              bslash, uscore, badchr:
  1442. X                error(ebadchar);
  1443. X
  1444. X            (* identifiers or keywords *)
  1445. X              'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
  1446. X              'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
  1447. X              'u', 'v', 'w', 'x', 'y', 'z',
  1448. X              'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
  1449. X              'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
  1450. X              'U', 'V', 'W', 'X', 'Y', 'Z':
  1451. X                begin
  1452. X                (* read token into buffer *)
  1453. X                wb[1] := lowercase(c);
  1454. X                wl := 2;
  1455. X                while (wl < maxtoknlen) and idchar(peekchar) do
  1456. X                    begin
  1457. X                    wb[wl] := lowercase(nextchar);
  1458. X                    wl := wl + 1
  1459. X                    end;
  1460. X                if wl >= maxtoknlen then
  1461. X                    begin
  1462. X                    lasttok[lastchr] := chr(null);
  1463. X                    error(elongtokn)
  1464. X                    end;
  1465. X                (* terminate token and match *)
  1466. X                wb[wl] := chr(null);
  1467. X                (* check if keyword/identifier *)
  1468. X                st := keywordcheck(wb, wl-1);
  1469. X                if st = sid then
  1470. X                    vid := saveid(wb)
  1471. X                end;
  1472. X
  1473. X            (* integer or real numbers *)
  1474. X              '0', '1', '2', '3', '4', '5', '6', '7' ,'8', '9':
  1475. X                begin
  1476. X                (* assume integer number, save it in buffer *)
  1477. X                wb[1] := c;
  1478. X                wl := 2;
  1479. X                n := numval(c);
  1480. X                while numchar(peekchar) do
  1481. X                    begin
  1482. X                    c := nextchar;
  1483. X                    n := n * 10 + numval(c);
  1484. X                    wb[wl] := c;
  1485. X                    wl := wl + 1
  1486. X                    end;
  1487. X                st := sinteger;
  1488. X                vint := n;
  1489. X                if realok then
  1490. X                    begin
  1491. X                    (* accept real numbers *)
  1492. X                    if peekchar = '.' then
  1493. X                        begin
  1494. X                        (* this is a real number *)
  1495. X                        st := sreal;
  1496. X                        wb[wl] := nextchar;
  1497. X                        wl := wl + 1;
  1498. X                        while numchar(peekchar) do
  1499. X                            begin
  1500. X                            wb[wl] := nextchar;
  1501. X                            wl := wl + 1
  1502. X                            end
  1503. X                        end;
  1504. X                    c := peekchar;
  1505. X                    if (c = 'e') or (c = 'E') then
  1506. X                        begin
  1507. X                        (* this is a real number *)
  1508. X                        st := sreal;
  1509. X                        c := nextchar;
  1510. X                        wb[wl] := xpnent;
  1511. X                        wl := wl + 1;
  1512. X                        c := peekchar;
  1513. X                        if (c = '-') or (c = '+') then
  1514. X                            begin
  1515. X                            wb[wl] := nextchar;
  1516. X                            wl := wl + 1
  1517. X                            end;
  1518. X                        while numchar(peekchar) do
  1519. X                            begin
  1520. X                            wb[wl] := nextchar;
  1521. X                            wl := wl + 1
  1522. X                            end
  1523. X                        end;
  1524. X                    if st = sreal then
  1525. X                        begin
  1526. X                        wb[wl] := chr(null);
  1527. X                        vflt := savestr(wb)
  1528. X                        end
  1529. X                    end
  1530. X                end;
  1531. X
  1532. X              '(':
  1533. X                if peekchar = '.' then
  1534. X                    begin
  1535. X                    (* some compilers on non-ascii systems
  1536. X                       use (. for [ and .) for ] *)
  1537. X                    c := nextchar;
  1538. X                    st := slbrack
  1539. X                    end
  1540. X                else
  1541. X                    st := slpar;
  1542. X              ')':
  1543. X                st := srpar;
  1544. X              '[':
  1545. X                st := slbrack;
  1546. X              ']':
  1547. X                st := srbrack;
  1548. X              '.':
  1549. X                if peekchar = '.' then
  1550. X                    begin
  1551. X                    c := nextchar;
  1552. X                    st := sdotdot
  1553. X                    end
  1554. X                else if peekchar = ')' then
  1555. X                    begin
  1556. X                    c := nextchar;
  1557. X                    st := srbrack
  1558. X                    end
  1559. X                else
  1560. X                    st := sdot;
  1561. X              ';':
  1562. X                st := ssemic;
  1563. X              ':':
  1564. X                if peekchar = '=' then
  1565. X                    begin
  1566. X                    c := nextchar;
  1567. X                    st := sassign
  1568. X                    end
  1569. X                else
  1570. X                    st := scolon;
  1571. X              ',':
  1572. X                st := scomma;
  1573. X              '@',
  1574. X              '^':
  1575. X                st := sarrow;
  1576. X              '=':
  1577. X                st := seq;
  1578. X              '<':
  1579. X                if peekchar = '=' then
  1580. X                    begin
  1581. X                    c := nextchar;
  1582. X                    st := sle
  1583. X                    end
  1584. X                else if peekchar = '>' then
  1585. X                    begin
  1586. X                    c := nextchar;
  1587. X                    st := sne
  1588. X                    end
  1589. X                else
  1590. X                    st := slt;
  1591. X              '>':
  1592. X                if peekchar = '=' then
  1593. X                    begin
  1594. X                    c := nextchar;
  1595. X                    st := sge
  1596. X                    end
  1597. X                else
  1598. X                    st := sgt;
  1599. X              '+':
  1600. X                st := splus;
  1601. X              '-':
  1602. X                st := sminus;
  1603. X              '*':
  1604. X                st := smul;
  1605. X              '/':
  1606. X                st := squot;
  1607. X              quote:
  1608. X                begin
  1609. X                (* assume the symbol is a literal string *)
  1610. X                wl := 0;
  1611. X                ready := false;
  1612. X                repeat
  1613. X                    if eoln then
  1614. X                        begin
  1615. X                        lasttok[lastchr] := chr(null);
  1616. X                        error(ebadstring)
  1617. X                        end;
  1618. X                    c := nextchar;
  1619. X                    if c = quote then
  1620. X                        if peekchar = quote then
  1621. X                            c := nextchar
  1622. X                        else
  1623. X                            ready := true;
  1624. X                    if c = chr(null) then
  1625. X                        begin
  1626. X                        if eof then
  1627. X                            error(eeofstr);
  1628. X                        lasttok[lastchr] := chr(null);
  1629. X                        error(enulchr)
  1630. X                        end;
  1631. X                    if not ready then
  1632. X                        begin
  1633. X                        wl := wl + 1;
  1634. X                        if wl >= maxtoknlen then
  1635. X                            begin
  1636. X                            lasttok[lastchr] :=
  1637. X                                chr(null);
  1638. X                            error(elongstring)
  1639. X                            end;
  1640. X                        wb[wl] := c
  1641. X                        end
  1642. X                until    ready;
  1643. X                if wl = 1 then
  1644. X                    begin
  1645. X                    (* only 1 character => not a string *)
  1646. X                    st := schar;
  1647. X                    vchr := wb[1]
  1648. X                    end
  1649. X                else begin
  1650. X                    (* > 1 character => its a string *)
  1651. X                    wl := wl + 1;
  1652. X                    if wl >= maxtoknlen then
  1653. X                        begin
  1654. X                        lasttok[lastchr] := chr(null);
  1655. X                        error(elongstring)
  1656. X                        end;
  1657. X                    wb[wl] := chr(null);
  1658. X                    st := sstring;
  1659. X                    vstr := savestr(wb)
  1660. X                     end
  1661. X                end
  1662. X
  1663. X            end;(* case *)
  1664. X        if lastchr = 0 then
  1665. X            lastchr := 1;
  1666. X        lasttok[lastchr] := chr(null)
  1667. X    end;    (* nexttoken *)
  1668. X
  1669. Xbegin    (* nextsymbol *)
  1670. X    nexttoken(sreal in ss);
  1671. X    checksymbol(ss)
  1672. Xend;    (* nextsymbol *)
  1673. X
  1674. X(*    Return a pointer to the node describing the type of tp. This    *)
  1675. X(*    function also stores the result in the node for future ref.    *)
  1676. Xfunction typeof(tp : treeptr) : treeptr;
  1677. X
  1678. Xvar    tf, tq    : treeptr;
  1679. X
  1680. Xbegin
  1681. X    tq := tp;
  1682. X    tf := tq^.ttype;
  1683. X    (* keep working until a type is found *)
  1684. X    while tf = nil do
  1685. X        begin
  1686. X        case tq^.tt of
  1687. X          nchar:
  1688. X            tf := typnods[tchar];
  1689. X
  1690. X          ninteger:
  1691. X            tf := typnods[tinteger];
  1692. X
  1693. X          nreal:
  1694. X            tf := typnods[treal];
  1695. X
  1696. X          nstring:
  1697. X            tf := typnods[tstring];
  1698. X
  1699. X          nnil:
  1700. X            tf := typnods[tnil];
  1701. X
  1702. X          nid:
  1703. X            begin
  1704. X            tq := idup(tq);
  1705. X            if tq = nil then
  1706. X                fatal(etree)
  1707. X            end;
  1708. X
  1709. X          ntype,
  1710. X          nvar,
  1711. X          nconst,
  1712. X          nfield,
  1713. X          nvalpar,
  1714. X          nvarpar:
  1715. X            tq := tq^.tbind;
  1716. X
  1717. X          npredef,
  1718. X          nptr,
  1719. X          nscalar,
  1720. X          nrecord,
  1721. X          nconfarr,
  1722. X          narray,
  1723. X          nfileof,
  1724. X          nsetof:
  1725. X            tf := tq;    (* these nodetypes represent types *)
  1726. X
  1727. X          nsubrange:
  1728. X            if tq^.tup^.tt = nconfarr then
  1729. X                tf := tq^.tup^.tindtyp
  1730. X            else
  1731. X                tf := tq;
  1732. X
  1733. X          ncall:
  1734. X            begin
  1735. X            tf := typeof(tq^.tcall);
  1736. X            if tf = typnods[tpoly] then
  1737. X                tf := typeof(tq^.taparm)
  1738. X            end;
  1739. X
  1740. X          nfunc:
  1741. X            tq := tq^.tfuntyp;
  1742. X
  1743. X          nparfunc:
  1744. X            tq := tq^.tpartyp;
  1745. X
  1746. X          nproc,
  1747. X          nparproc:
  1748. X            tf := typnods[tnone];
  1749. X
  1750. X          nvariant,
  1751. X          nlabel,
  1752. X          npgm,
  1753. X          nempty,
  1754. X          nbegin,
  1755. X          nlabstmt,
  1756. X          nassign,
  1757. X          npush,
  1758. X          npop,
  1759. X          nif,
  1760. X          nwhile,
  1761. X          nrepeat,
  1762. X          nfor,
  1763. X          ncase,
  1764. X          nchoise,
  1765. X          ngoto,
  1766. X          nwith,
  1767. X          nwithvar:
  1768. X            fatal(etree);
  1769. X
  1770. X          nformat,
  1771. X          nrange:
  1772. X            tq := tq^.texpl;
  1773. X
  1774. X          nplus,
  1775. X          nminus,
  1776. X          nmul:
  1777. X            begin
  1778. X            tf := typeof(tq^.texpl);
  1779. X            if tf = typnods[tinteger] then
  1780. X                tf := typeof(tq^.texpr)
  1781. X            else if tf^.tt = nsetof then
  1782. X                tf := typnods[tset]
  1783. X            end;
  1784. X
  1785. X          numinus,
  1786. X          nuplus:
  1787. X            tq := tq^.texps;
  1788. X
  1789. X          nmod,
  1790. X          ndiv:
  1791. X            tf := typnods[tinteger];
  1792. X
  1793. X          nquot:
  1794. X            tf := typnods[treal];
  1795. X
  1796. X          neq,
  1797. X          nne,
  1798. X          nlt,
  1799. X          nle,
  1800. X          ngt,
  1801. X          nge,
  1802. X          nin,
  1803. X          nor,
  1804. X          nand,
  1805. X          nnot:
  1806. X            tf := typnods[tboolean];
  1807. X
  1808. X          nset:
  1809. X            tf := typnods[tset];
  1810. X
  1811. X          nselect:
  1812. X            tq := tq^.tfield;
  1813. X
  1814. X          nderef:
  1815. X            begin
  1816. X            tq := typeof(tq^.texps);
  1817. X            case tq^.tt of
  1818. X              nptr:
  1819. X                tq := tq^.tptrid;
  1820. X              nfileof:
  1821. X                tq := tq^.tof;
  1822. X              npredef:
  1823. X                tf := typnods[tchar]    (* textfile *)
  1824. X            end (* case *)
  1825. X            end;
  1826. X
  1827. X          nindex:
  1828. X            begin
  1829. X            tq := typeof(tq^.tvariable);
  1830. X            if tq^.tt = nconfarr then
  1831. X                tq := tq^.tcelem
  1832. X            else if tq = typnods[tstring] then
  1833. X                tf := typnods[tchar]
  1834. X            else
  1835. X                tq := tq^.taelem
  1836. X            end;
  1837. X
  1838. X        end (* case *)
  1839. X    end;
  1840. X    if tp^.ttype = nil then
  1841. X        tp^.ttype := tf;    (* remember type for future reference *)
  1842. X    typeof := tf
  1843. Xend;    (* typeof *)
  1844. X
  1845. X(*    Connect all nodes to their fathers.                *)
  1846. Xprocedure linkup(up, tp : treeptr);
  1847. X
  1848. Xbegin
  1849. X    while tp <> nil do
  1850. X        begin
  1851. X        if tp^.tup = nil then
  1852. X            begin
  1853. X            tp^.tup := up;
  1854. X            case tp^.tt of
  1855. X              npgm,
  1856. X              nfunc,
  1857. X              nproc:
  1858. X                begin
  1859. X                linkup(tp, tp^.tsubid);
  1860. X                linkup(tp, tp^.tsubpar);
  1861. X                linkup(tp, tp^.tfuntyp);
  1862. X                linkup(tp, tp^.tsublab);
  1863. X                linkup(tp, tp^.tsubconst);
  1864. X                linkup(tp, tp^.tsubtype);
  1865. X                linkup(tp, tp^.tsubvar);
  1866. X                linkup(tp, tp^.tsubsub);
  1867. X                linkup(tp, tp^.tsubstmt)
  1868. X                end;
  1869. X
  1870. X
  1871. X              nvalpar,
  1872. X              nvarpar,
  1873. X              nconst,
  1874. X              ntype,
  1875. X              nfield,
  1876. X              nvar:
  1877. X                begin
  1878. X                linkup(tp, tp^.tidl);
  1879. X                linkup(tp, tp^.tbind)
  1880. X                end;
  1881. X
  1882. X              nparproc,
  1883. X              nparfunc:
  1884. X                begin
  1885. X                linkup(tp, tp^.tparid);
  1886. X                linkup(tp, tp^.tparparm);
  1887. X                linkup(tp, tp^.tpartyp)
  1888. X                end;
  1889. X
  1890. X              nptr:
  1891. X                linkup(tp, tp^.tptrid);
  1892. X              nscalar:
  1893. X                linkup(tp, tp^.tscalid);
  1894. X
  1895. X              nsubrange:
  1896. X                begin
  1897. X                linkup(tp, tp^.tlo);
  1898. X                linkup(tp, tp^.thi)
  1899. X                end;
  1900. X              nvariant:
  1901. X                begin
  1902. X                linkup(tp, tp^.tselct);
  1903. X                linkup(tp, tp^.tvrnt)
  1904. X                end;
  1905. X              nrecord:
  1906. X                begin
  1907. X                linkup(tp, tp^.tflist);
  1908. X                linkup(tp, tp^.tvlist)
  1909. X                end;
  1910. X              nconfarr:
  1911. X                begin
  1912. X                linkup(tp, tp^.tcindx);
  1913. X                linkup(tp, tp^.tcelem);
  1914. X                linkup(tp, tp^.tindtyp)
  1915. X                end;
  1916. X              narray:
  1917. X                begin
  1918. X                linkup(tp, tp^.taindx);
  1919. X                linkup(tp, tp^.taelem)
  1920. X                end;
  1921. X              nfileof,
  1922. X              nsetof:
  1923. X                linkup(tp, tp^.tof);
  1924. X              nbegin:
  1925. X                linkup(tp, tp^.tbegin);
  1926. X              nlabstmt:
  1927. X                begin
  1928. X                linkup(tp, tp^.tlabno);
  1929. X                linkup(tp, tp^.tstmt)
  1930. X                end;
  1931. X              nassign:
  1932. X                begin
  1933. X                linkup(tp, tp^.tlhs);
  1934. X                linkup(tp, tp^.trhs)
  1935. X                end;
  1936. X              npush,
  1937. X              npop:
  1938. X                begin
  1939. X                linkup(tp, tp^.tglob);
  1940. X                linkup(tp, tp^.tloc);
  1941. X                linkup(tp, tp^.ttmp)
  1942. X                end;
  1943. X              ncall:
  1944. X                begin
  1945. X                linkup(tp, tp^.tcall);
  1946. X                linkup(tp, tp^.taparm )
  1947. X                end;
  1948. X              nif:
  1949. X                begin
  1950. X                linkup(tp, tp^.tifxp);
  1951. X                linkup(tp, tp^.tthen);
  1952. X                linkup(tp, tp^.telse)
  1953. X                end;
  1954. X              nwhile:
  1955. X                begin
  1956. X                linkup(tp, tp^.twhixp);
  1957. X                linkup(tp, tp^.twhistmt)
  1958. X                end;
  1959. X              nrepeat:
  1960. X                begin
  1961. X                linkup(tp, tp^.treptstmt);
  1962. X                linkup(tp, tp^.treptxp)
  1963. X                end;
  1964. X              nfor:
  1965. X                begin
  1966. X                linkup(tp, tp^.tforid);
  1967. X                linkup(tp, tp^.tfrom);
  1968. X                linkup(tp, tp^.tto);
  1969. X                linkup(tp, tp^.tforstmt)
  1970. X                end;
  1971. X              ncase:
  1972. X                begin
  1973. X                linkup(tp, tp^.tcasxp);
  1974. X                linkup(tp, tp^.tcaslst);
  1975. X                linkup(tp, tp^.tcasother)
  1976. X                end;
  1977. X              nchoise:
  1978. X                begin
  1979. X                linkup(tp, tp^.tchocon);
  1980. X                linkup(tp, tp^.tchostmt)
  1981. X                end;
  1982. X              nwith:
  1983. X                begin
  1984. X                linkup(tp, tp^.twithvar);
  1985. X                linkup(tp, tp^.twithstmt)
  1986. X                end;
  1987. X              nwithvar:
  1988. X                linkup(tp, tp^.texpw);
  1989. X              nindex:
  1990. X                begin
  1991. X                linkup(tp, tp^.tvariable);
  1992. X                linkup(tp, tp^.toffset)
  1993. X                end;
  1994. X              nselect:
  1995. X                begin
  1996. X                linkup(tp, tp^.trecord);
  1997. X                linkup(tp, tp^.tfield)
  1998. X                end;
  1999. X
  2000. X              ngoto:
  2001. X                linkup(tp, tp^.tlabel);
  2002. X
  2003. X              nrange, nformat,
  2004. X              nin, neq,
  2005. X              nne, nlt, nle,
  2006. X              ngt, nge, nor,
  2007. X              nplus, nminus,
  2008. X              nand, nmul,
  2009. X              ndiv, nmod,
  2010. X              nquot:
  2011. X                begin
  2012. X                linkup(tp, tp^.texpl);
  2013. X                linkup(tp, tp^.texpr)
  2014. X                end;
  2015. X
  2016. X              nderef,
  2017. X              nnot, nset,
  2018. X              numinus,
  2019. X              nuplus:
  2020. X                linkup(tp, tp^.texps);
  2021. X
  2022. X              nid,
  2023. X              nnil, ninteger,
  2024. X              nreal, nchar,
  2025. X              nstring, npredef,
  2026. X              nlabel, nempty:
  2027. X                (* no op *)
  2028. X            end (* case *)
  2029. X        end;
  2030. X        tp := tp^.tnext
  2031. X        end
  2032. Xend;    (* linkup *)
  2033. X
  2034. X(*    Allocate a new symbol node.                    *)
  2035. Xfunction mksym(vt : ltypes) : symptr;
  2036. X
  2037. Xvar    mp    : symptr;
  2038. X
  2039. Xbegin
  2040. X    new(mp);
  2041. X    if mp = nil then
  2042. X        error(enew);
  2043. X    mp^.lt := vt;
  2044. X    mp^.lnext := nil;
  2045. X    mp^.lsymdecl := nil;
  2046. X    mp^.ldecl := nil;
  2047. X    mksym := mp
  2048. Xend;
  2049. X
  2050. X(*    Enter a symbol at current declarationlevel.            *)
  2051. Xprocedure declsym(sp : symptr);
  2052. X
  2053. Xvar    h    : hashtyp;
  2054. X
  2055. Xbegin
  2056. X    if sp^.lt in [lpredef, lidentifier, lfield, lforward, lpointer] then
  2057. X        h := sp^.lid^.ihash
  2058. X    else
  2059. X        h := hashmax;
  2060. X    sp^.lnext := symtab^.ddecl[h];
  2061. X    symtab^.ddecl[h] := sp;
  2062. X    sp^.ldecl := symtab
  2063. Xend;
  2064. X
  2065. X(*    Create a node of selected type.                    *)
  2066. Xfunction mknode(nt : treetyp) : treeptr;
  2067. X
  2068. Xvar    tp    : treeptr;
  2069. X
  2070. Xbegin
  2071. X    tp := nil;
  2072. X    case nt of
  2073. X      npredef:    new(tp, npredef);
  2074. X      npgm:        new(tp, npgm);
  2075. X      nfunc:    new(tp, nfunc);
  2076. X      nproc:    new(tp, nproc);
  2077. X      nlabel:    new(tp, nlabel);
  2078. X      nconst:    new(tp, nconst);
  2079. X      ntype:    new(tp, ntype);
  2080. X      nvar:        new(tp, nvar);
  2081. X      nvalpar:    new(tp, nvalpar);
  2082. X      nvarpar:    new(tp, nvarpar);
  2083. X      nparproc:    new(tp, nparproc);
  2084. X      nparfunc:    new(tp, nparfunc);
  2085. X      nsubrange:    new(tp, nsubrange);
  2086. X      nvariant:    new(tp, nvariant);
  2087. X      nfield:    new(tp, nfield);
  2088. X      nrecord:    new(tp, nrecord);
  2089. X      nconfarr:    new(tp, nconfarr);
  2090. X      narray:    new(tp, narray);
  2091. X      nfileof:    new(tp, nfileof);
  2092. X      nsetof:    new(tp, nsetof);
  2093. X      nbegin:    new(tp, nbegin);
  2094. X      nptr:        new(tp, nptr);
  2095. X      nscalar:    new(tp, nscalar);
  2096. X      nif:        new(tp, nif);
  2097. X      nwhile:    new(tp, nwhile);
  2098. X      nrepeat:    new(tp, nrepeat);
  2099. X      nfor:        new(tp, nfor);
  2100. X      ncase:    new(tp, ncase);
  2101. X      nchoise:    new(tp, nchoise);
  2102. X      ngoto:    new(tp, ngoto);
  2103. X      nwith:    new(tp, nwith);
  2104. X      nwithvar:    new(tp, nwithvar);
  2105. X      nempty:    new(tp, nempty);
  2106. X      nlabstmt:    new(tp, nlabstmt);
  2107. X      nassign:    new(tp, nassign);
  2108. X      nformat:    new(tp, nformat);
  2109. X      nin:        new(tp, nin);
  2110. X      neq:        new(tp, neq);
  2111. X      nne:        new(tp, nne);
  2112. X      nlt:        new(tp, nlt);
  2113. X      nle:        new(tp, nle);
  2114. X      ngt:        new(tp, ngt);
  2115. X      nge:        new(tp, nge);
  2116. X      nor:        new(tp, nor);
  2117. X      nplus:    new(tp, nplus);
  2118. X      nminus:    new(tp, nminus);
  2119. X      nand:        new(tp, nand);
  2120. X      nmul:        new(tp, nmul);
  2121. X      ndiv:        new(tp, ndiv);
  2122. X      nmod:        new(tp, nmod);
  2123. X      nquot:    new(tp, nquot);
  2124. X      nnot:        new(tp, nnot);
  2125. X      numinus:    new(tp, numinus);
  2126. X      nuplus:    new(tp, nuplus);
  2127. X      nset:        new(tp, nset);
  2128. X      nrange:    new(tp, nrange);
  2129. X      nindex:    new(tp, nindex);
  2130. X      nselect:    new(tp, nselect);
  2131. X      nderef:    new(tp, nderef);
  2132. X      ncall:    new(tp, ncall);
  2133. X      nid:        new(tp, nid);
  2134. X      nchar:    new(tp, nchar);
  2135. X      ninteger:    new(tp, ninteger);
  2136. X      nreal:    new(tp, nreal);
  2137. X      nstring:    new(tp, nstring);
  2138. X      nnil:        new(tp, nnil);
  2139. X      npush:    new(tp, npush);
  2140. X      npop:        new(tp, npop);
  2141. X      nbreak:    new(tp, nbreak)
  2142. X    end;(* case *)
  2143. X    if tp = nil then
  2144. X        error(enew);
  2145. X    tp^.tt := nt;
  2146. X    tp^.tnext := nil;
  2147. X    tp^.tup := nil;
  2148. X    tp^.ttype := nil;
  2149. X    mknode := tp
  2150. Xend;
  2151. X
  2152. X(*    Create a node with a literal value.                *)
  2153. Xfunction mklit : treeptr;
  2154. X
  2155. Xvar    sp    : symptr;
  2156. X    tp    : treeptr;
  2157. X
  2158. Xbegin
  2159. X    case currsym.st of
  2160. X      sinteger:
  2161. X        begin
  2162. X        sp := mksym(linteger);
  2163. X        sp^.linum := currsym.vint;
  2164. X        tp := mknode(ninteger);
  2165. X        end;
  2166. X      sreal:
  2167. X        begin
  2168. X        sp := mksym(lreal);
  2169. X        sp^.lfloat := currsym.vflt;
  2170. X        tp := mknode(nreal);
  2171. X        end;
  2172. X      schar:
  2173. X        begin
  2174. X        sp := mksym(lcharacter);
  2175. X        sp^.lchar := currsym.vchr;
  2176. X        tp := mknode(nchar);
  2177. X        end;
  2178. X      sstring:
  2179. X        begin
  2180. X        sp := mksym(lstring);
  2181. X        sp^.lstr := currsym.vstr;
  2182. X        tp := mknode(nstring);
  2183. X        end
  2184. X    end;(* case *)
  2185. X    tp^.tsym := sp;
  2186. X    sp^.lsymdecl := tp;
  2187. X    mklit := tp
  2188. Xend;
  2189. X
  2190. X(*    Look up an identifier among declared symbols.            *)
  2191. Xfunction lookupid(ip : idptr; fieldok : boolean) : symptr;
  2192. X
  2193. Xlabel    999;
  2194. X
  2195. Xvar    sp    : symptr;
  2196. X    dp    : declptr;
  2197. X    vs    : set of ltypes;
  2198. X
  2199. Xbegin
  2200. X    lookupid := nil;
  2201. X    if fieldok then
  2202. X        vs := [lidentifier, lforward, lpointer, lfield]
  2203. X    else
  2204. X        vs := [lidentifier, lforward, lpointer];
  2205. X    sp := nil;
  2206. X
  2207. X    (* pick up symboltable from innermost scope *)
  2208. X    dp := symtab;
  2209. X    while dp <> nil do
  2210. X        begin
  2211. X        (* scan linked symbols with same hasvalue *) 
  2212. X        sp := dp^.ddecl[ip^.ihash];
  2213. X        while sp <> nil do
  2214. X            begin
  2215. X            (* break out when proper id found *)
  2216. X            if (sp^.lt in vs) and (sp^.lid = ip) then
  2217. X                goto 999;
  2218. X            sp := sp^.lnext
  2219. X            end;
  2220. X        (* proceed to enclosing scope *)
  2221. X        dp := dp^.dprev
  2222. X        end;
  2223. X999:
  2224. X    lookupid := sp
  2225. Xend;
  2226. X
  2227. X(*    Look up a label.                        *)
  2228. Xfunction lookuplabel(i : integer) : symptr;
  2229. X
  2230. Xlabel    999;
  2231. X
  2232. Xvar    sp    : symptr;
  2233. X    dp    : declptr;
  2234. X
  2235. Xbegin
  2236. X    sp := nil;
  2237. X    dp := symtab;
  2238. X    while dp <> nil do
  2239. X        begin
  2240. X        sp := dp^.ddecl[hashmax];
  2241. X        while sp <> nil do
  2242. X            begin
  2243. X            if (sp^.lt in [lforwlab, llabel]) and (sp^.lno = i) then
  2244. X                goto 999;
  2245. X            sp := sp^.lnext
  2246. X            end;
  2247. X        dp := dp^.dprev
  2248. X        end;
  2249. X999:
  2250. X    lookuplabel := sp
  2251. Xend;
  2252. X
  2253. X(*    Create a new declaration level (a new scope) link declnode to    *)
  2254. X(*    previous node.    dp is non-nil when a procedure/function body    *)
  2255. X(*    is encountered for which we have seen a forward declaration.     *)
  2256. Xprocedure enterscope(dp : declptr);
  2257. X
  2258. Xvar    h    : hashtyp;
  2259. X
  2260. Xbegin
  2261. X    if dp = nil then
  2262. X        begin
  2263. X        new(dp);
  2264. X        for h := 0 to hashmax do
  2265. X            dp^.ddecl[h] := nil
  2266. X        end;
  2267. X    dp^.dprev := symtab;
  2268. X    symtab := dp
  2269. Xend;
  2270. X
  2271. X(*    Return current scope (as a pointer to symbol-table).    *)
  2272. Xfunction currscope : declptr;
  2273. X
  2274. Xbegin
  2275. X    currscope := symtab
  2276. Xend;
  2277. X
  2278. X(*    Drop innermost declaration scope.                *)
  2279. Xprocedure leavescope;
  2280. X
  2281. Xbegin
  2282. X    symtab := symtab^.dprev
  2283. Xend;
  2284. X
  2285. X(*    Create a new identifier symbol.                    *)
  2286. Xfunction mkid(ip : idptr) : symptr;
  2287. X
  2288. Xvar    sp    : symptr;
  2289. X
  2290. Xbegin
  2291. X    sp := mksym(lidentifier);
  2292. X    sp^.lid := ip;
  2293. X    sp^.lused := false;
  2294. X    declsym(sp);
  2295. X    ip^.inref := ip^.inref + 1;
  2296. X    mkid := sp
  2297. Xend;
  2298. X
  2299. X(*    Check that the current identifier is new then save it in the    *)
  2300. X(*    current scope. Create and return a new node representing this    *)
  2301. X(*    instance of the identifier.                    *)
  2302. Xfunction newid(ip : idptr) : treeptr;
  2303. X
  2304. Xvar    sp    : symptr;
  2305. X    tp    : treeptr;
  2306. X
  2307. Xbegin
  2308. X    sp := lookupid(ip, false);
  2309. X    if sp <> nil then
  2310. X        if sp^.ldecl <> symtab then
  2311. X            sp := nil;
  2312. X    if sp = nil then
  2313. X        begin
  2314. X        (* new identifier *)
  2315. X        tp := mknode(nid);
  2316. X        sp := mkid(ip);
  2317. X        sp^.lsymdecl := tp;
  2318. X        tp^.tsym := sp
  2319. X        end
  2320. X    else if sp^.lt = lpointer then
  2321. X        begin
  2322. X        (* previously declared as a pointer type *)
  2323. X        tp := mknode(nid);
  2324. X        tp^.tsym := sp;
  2325. X        sp^.lt := lidentifier;
  2326. X        sp^.lsymdecl := tp
  2327. X        end
  2328. X    else if sp^.lt = lforward then
  2329. X        begin
  2330. X        (* previously forward declared *)
  2331. X        sp^.lt := lidentifier;
  2332. X        tp := sp^.lsymdecl
  2333. X        end
  2334. X    else
  2335. X        error(emultdeclid);
  2336. X    newid := tp
  2337. Xend;
  2338. X
  2339. X(*    Check that the current identifier is already declared,    *)
  2340. X(*    we fail unless l in [lforward, lpointer].        *)
  2341. X(*    Create and return a new node referencing it.        *)
  2342. Xfunction oldid(ip : idptr; l : ltypes) : treeptr;
  2343. X
  2344. Xvar    sp    : symptr;
  2345. X    tp    : treeptr;
  2346. X
  2347. Xbegin
  2348. X    sp := lookupid(ip, true);
  2349. X    if sp = nil then
  2350. X        begin
  2351. X        if l in [lforward, lpointer] then
  2352. X            begin
  2353. X            tp := newid(ip);
  2354. X            tp^.tsym^.lt := l
  2355. X            end
  2356. X        else
  2357. X            error(enotdeclid)
  2358. X        end
  2359. X    else begin
  2360. X        sp^.lused := true;
  2361. X        tp := mknode(nid);
  2362. X        tp^.tsym := sp;
  2363. X        if (sp^.lt = lpointer) and (l = lidentifier) then
  2364. X            begin
  2365. X            sp^.lt := lidentifier;
  2366. X            sp^.lsymdecl := tp
  2367. X            end
  2368. X         end;
  2369. X    oldid := tp
  2370. Xend;
  2371. X
  2372. X(*    Look up a field in a record declaration.            *)
  2373. X(*    Return nil if field isn't declared in "tp" or its variants.    *)
  2374. Xfunction oldfield(tp : treeptr; ip : idptr) : treeptr;
  2375. X
  2376. Xlabel    999;
  2377. X
  2378. Xvar    tq, ti,
  2379. X    fp    : treeptr;
  2380. X
  2381. Xbegin
  2382. X    fp := nil;
  2383. X    tq := tp^.tflist;
  2384. X    while tq <> nil do
  2385. X        begin
  2386. X        ti := tq^.tidl;
  2387. X        while ti <> nil do
  2388. X            begin
  2389. X            if ti^.tsym^.lid = ip then
  2390. X                begin
  2391. X                fp := mknode(nid);
  2392. X                fp^.tsym := ti^.tsym;
  2393. X                goto 999
  2394. X                end;
  2395. X            ti := ti^.tnext
  2396. X            end;
  2397. X        tq := tq^.tnext
  2398. X        end;
  2399. X    tq := tp^.tvlist;
  2400. X    while tq <> nil do
  2401. X        begin
  2402. X        fp := oldfield(tq^.tvrnt, ip);
  2403. X        if fp <> nil then
  2404. X            tq := nil
  2405. X        else
  2406. X            tq := tq^.tnext
  2407. X        end;
  2408. X999:
  2409. X    oldfield := fp
  2410. Xend;
  2411. X
  2412. X(*    This is the main parsing routine. It parses a correct pascal-    *)
  2413. X(*    program and builds a parsetree which is left in the global    *)
  2414. X(*    variable top.                            *)
  2415. X(*    Parsing is done through recursive descent using a set of    *)
  2416. X(*    mutually recursive functions.                    *)
  2417. Xprocedure parse;
  2418. X
  2419. X    function plabel : treeptr;                forward;
  2420. X    function pidlist(l : ltypes) : treeptr;            forward;
  2421. X    function pconst : treeptr;                forward;
  2422. X    function pconstant(realok : boolean) : treeptr;        forward;
  2423. X    function precord(cs : symtyp; dp : declptr) : treeptr;    forward;
  2424. X    function ptypedef : treeptr;                forward;
  2425. X    function ptype : treeptr;                forward;
  2426. X    function pvar : treeptr;                forward;
  2427. X    function psubs : treeptr;                forward;
  2428. X    function psubpar : treeptr;                forward;
  2429. X    function plabstmt : treeptr;                forward;
  2430. X    function pstmt : treeptr;                forward;
  2431. X    function psimple : treeptr;                forward;
  2432. X    function pvariable(varptr : treeptr) : treeptr;        forward;
  2433. X    function pexpr(tnp : treeptr) : treeptr;        forward;
  2434. X    function pcase : treeptr;                forward;
  2435. X    function pif : treeptr;                    forward;
  2436. X    function pwhile : treeptr;                forward;
  2437. X    function prepeat : treeptr;                forward;
  2438. X    function pfor : treeptr;                forward;
  2439. X    function pwith : treeptr;                forward;
  2440. X    function pgoto : treeptr;                forward;
  2441. X    function pbegin(retain : boolean) : treeptr;        forward;
  2442. X
  2443. X    (*    Open scope of a record variable.            *)
  2444. X    procedure scopeup(tp : treeptr);
  2445. X
  2446. X        (*    Scan a record-declaration and add all fields to    *)
  2447. X        (*    current scope.                    *)
  2448. X        procedure addfields(rp : treeptr);
  2449. X
  2450. X        var    fp, ip, vp    : treeptr;
  2451. X            sp        : symptr;
  2452. X
  2453. X        begin
  2454. X            fp := rp^.tflist;
  2455. X            while fp <> nil do
  2456. X                begin
  2457. X                ip := fp^.tidl;
  2458. X                while ip <> nil do
  2459. X                    begin
  2460. X                    sp := mksym(lfield);
  2461. X                    sp^.lid := ip^.tsym^.lid;
  2462. X                    sp^.lused := false;
  2463. X                    sp^.lsymdecl := ip;
  2464. X                    declsym(sp);
  2465. X                    ip := ip^.tnext
  2466. X                    end;
  2467. X                fp := fp^.tnext
  2468. X                end;
  2469. X            vp := rp^.tvlist;
  2470. X            while vp <> nil do
  2471. X                begin
  2472. X                addfields(vp^.tvrnt);
  2473. X                vp := vp^.tnext
  2474. X                end
  2475. X        end;
  2476. X    begin
  2477. X        addfields(typeof(tp))
  2478. X    end;
  2479. X
  2480. X    (*    Check that the current label is new then save it in the    *)
  2481. X    (*    current scope. Create and return a new node referencing    *)
  2482. X    (*    the label.                        *)
  2483. X    function newlbl : treeptr;
  2484. X
  2485. X    var    sp    : symptr;
  2486. X        tp    : treeptr;
  2487. X
  2488. X    begin
  2489. X        tp := mknode(nlabel);
  2490. X        sp := lookuplabel(currsym.vint);
  2491. X        if sp <> nil then
  2492. X            if sp^.ldecl <> symtab then
  2493. X                sp := nil;
  2494. X        if sp = nil then
  2495. X            begin
  2496. X            sp := mksym(lforwlab);
  2497. X            sp^.lno := currsym.vint;
  2498. X            sp^.lgo := false;
  2499. X            sp^.lsymdecl := tp;
  2500. X            declsym(sp)
  2501. X            end
  2502. X        else
  2503. X            error(emultdecllab);
  2504. X        tp^.tsym := sp;
  2505. X        newlbl := tp
  2506. X    end;
  2507. X
  2508. X    (*    Check that the current label is already declared.    *)
  2509. X    (*    Create and return a new node referencing it.        *)
  2510. X    function oldlbl(defpt : boolean) : treeptr;
  2511. X
  2512. X    var    sp    : symptr;
  2513. X        tp    : treeptr;
  2514. X
  2515. X    begin
  2516. X        sp := lookuplabel(currsym.vint);
  2517. X        if sp = nil then
  2518. X            begin
  2519. X            prtmsg(enotdecllab);
  2520. X            tp := newlbl;
  2521. X            sp := tp^.tsym
  2522. X            end
  2523. X        else begin
  2524. X            tp := mknode(nlabel);
  2525. X            tp^.tsym := sp
  2526. X             end;
  2527. X        if defpt then
  2528. X            begin
  2529. X
  2530. END_OF_FILE
  2531. if test 59347 -ne `wc -c <'ptc.p.1'`; then
  2532.     echo shar: \"'ptc.p.1'\" unpacked with wrong size!
  2533. fi
  2534. # end of 'ptc.p.1'
  2535. fi
  2536. echo shar: End of archive 12 \(of 12\).
  2537. cp /dev/null ark12isdone
  2538. MISSING=""
  2539. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  2540.     if test ! -f ark${I}isdone ; then
  2541.     MISSING="${MISSING} ${I}"
  2542.     fi
  2543. done
  2544. if test "${MISSING}" = "" ; then
  2545.     echo You have unpacked all 12 archives.
  2546.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2547. else
  2548.     echo You still need to unpack the following archives:
  2549.     echo "        " ${MISSING}
  2550. fi
  2551. ##  End of shell archive.
  2552. exit 0
  2553. -- 
  2554.  
  2555. Rich $alz            "Anger is an energy"
  2556. Cronus Project, BBN Labs    rsalz@bbn.com
  2557. Moderator, comp.sources.unix    sources@uunet.uu.net
  2558.